package com.jplus.core.utill;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * LRU缓存， 当缓存满时，会优先淘汰那些近期最少使用的缓存对象。
 */
public class LRUCache<K, V> extends LinkedHashMap<K, V> {
	private static final long serialVersionUID = 1L;
	private static Lock lk = new ReentrantLock();
	private int capacity;

	public LRUCache(int capacity) {
		super(capacity, 0.75f, true);
		this.capacity = capacity;
	}

	@Override
	protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
		return size() > capacity;
	}

	/**
	 * 获取缓存。如果不存在，则重载
	 * 
	 * <pre>
	 * String value = cache.get(key, (o1) -> {
	 * 	// example
	 * 	return redis.get(o1);
	 * });
	 * </pre>
	 */
	public V get(K key, Reload<K, V> reload) {
		V value = get(key);
		if (value == null) {
			lk.lock();// 排它锁
			try {
				if (value == null)// 二次校验
					value = reload.get(key);
				if (value != null)
					put(key, value);
			} finally {
				lk.unlock();
			}
		}
		return value;
	}

	/** 重载最新数据 */
	public static interface Reload<K, V> {
		V get(K o1);
	}
}